using System.Globalization;
using System.Security.Claims;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Services.Identity.Domain.Entities;
using Services.Identity.Domain.ValueObject;
using Services.Initial.PublicProject.PublicClass.ExtensionException;
using Zack.JWT;

namespace Services.Identity.Domain;
public class IDomainService
{
    private readonly ITokenService tokenService;
    private readonly IIdentityRepository identityRepositary;
    private readonly JWTOptions jWTOptions;
    private readonly ILogger<IDomainService> logger;
    public IDomainService(IIdentityRepository identityRepositary, ITokenService tokenService, IOptions<JWTOptions> options, ILogger<IDomainService> logger)
    {
        this.identityRepositary = identityRepositary;
        this.tokenService = tokenService;
        this.jWTOptions = options.Value;
        this.logger = logger;
    }

    public Task<IdentityResult> AddUserAsync(string userName, string userPhone, string password)
    {
        return this.identityRepositary.AddUserAsync(userName, userPhone, password);
    }

    public async Task<IdentityResult> AddUserToRoleAsync(string userName, string roleName)
    {
        return await this.identityRepositary.AddUserToRoleAsync(userName, roleName);
    }

    public async Task<IdentityResult> CreateRoleAsync(string roleName)
    {
        return await this.identityRepositary.AddRoleAsync(roleName);
    }

    public Task<IdentityResult> DeleteRoleAsync(string roleName)
    {
        return this.identityRepositary.DeleteRoleAsync(roleName);
    }

    public Task<IdentityResult> DeleteUserAsync(string userName)
    {
        return this.identityRepositary.DeleteUserAsync(userName);
    }

    public Task<string[]> GetAllRoleNamesAsync()
    {
        return this.identityRepositary.GetAllRoleNamesAsync();
    }

    public async Task<string> GetRoleByUserIdAsync(User user)
    {
        var roles = await this.identityRepositary.GetRolesByUserAsync(user);
        foreach (var item in roles)
        {
            return item;
        }
        throw new ExceptionWithStatus(httpStatusCode: System.Net.HttpStatusCode.NotFound, $"未找到{user.UserName}对应的信息");
    }

    public Task<User> GetUserInfoByIdAsync(string id)
    {
        return this.identityRepositary.GetUserInformationByIdAsync(id);
    }
    public Task<List<User>> GetUserInfoByNameAsync(string name)
    {
        return this.identityRepositary.GetUserInformationByNamesync(name);
    }
    public async Task<(IdentityResult result, string? token)> LoginByUserNameAsync(string userName, string password)
    {
        var (result, user) = await this.identityRepositary.CheckUserNameAndPasswordAsync(userName, password);
        var token = await BuildTokenAsync(user);
        return (result, token);
    }

    public async Task<(IdentityResult result, string token)> LoginByUserPhoneAsync(string userPhone, string password)
    {
        var (result, user) = await this.identityRepositary.CheckUserPhoneAndPasswordAsync(userPhone, password);
        var token = await BuildTokenAsync(user);
        return (result, token);
    }
    public async Task<bool> AddRolePermissionsAsync(string roleName,List<PermissionNameAndRouter> permissions)
    {
        var role = await this.identityRepositary.GetRoleAsync(roleName);
        var result = await this.identityRepositary.AddRolePermissionsAsync(role, permissions);
        return result;
    }

    private async Task<string> BuildTokenAsync(User user)
    {
        var roles = await this.identityRepositary.GetRolesByUserAsync(user);
        var claims = new List<Claim>
        {
            new(ClaimTypes.NameIdentifier, user.Id.ToString())
        };
        foreach (string role in roles)
        {
            claims.Add(new Claim(ClaimTypes.Role, role));
        }
        return tokenService.BuildToken(claims, this.jWTOptions);
    }

    public async Task<bool> DeleteRolePermissionsAsync(string roleName, string[] permissions)
    {
        var role = await this.identityRepositary.GetRoleAsync(roleName);
        var result = await this.identityRepositary.DeleteRolePermissionsAsync(role, permissions);
        return result;
    }

    public async Task<List<PermissionNameAndRouter>> GetRolePermissionsAsync(string roleName)
    {
        var role  = await this.identityRepositary.GetRoleAsync(roleName);
        return await this.identityRepositary.GetRolePermissionsAsync(role);
    }
}